#include "cbc_mode.h"

int C_CBC_MODE::Encrypt(BYTE* pIn, int iLenIn, BYTE* pOut, int* piLenOut, IBlockCipherKernel* pobjKer)
{
    int iBlock  = pobjKer->GetBlockLen();
    int& iWrite = *piLenOut;

    iWrite = 0;
    while(iWrite + iBlock <= iLenIn)
    {
        for(int i = 0; i < 16; i++) m_bfIV[i] ^= pIn[iWrite + i];
        pobjKer->Encrypt(m_bfIV, pOut + iWrite);
        memcpy(m_bfIV, pOut + iWrite, 16);
        iWrite += iBlock;
    }

    return 0;
}

int C_CBC_MODE::Decrypt(BYTE* pIn, int iLenIn, BYTE* pOut, int* piLenOut, IBlockCipherKernel* pobjKer)
{
    int iBlock  = pobjKer->GetBlockLen();
    int& iWrite = *piLenOut;

    iWrite = 0;
    while(iWrite + iBlock <= iLenIn)
    {
        pobjKer->Decrypt(pIn + iWrite, pOut + iWrite);
        for(int i = 0; i < 16; i++) pOut[iWrite + i] ^= m_bfIV[i];
        memcpy(m_bfIV, pIn + iWrite, 16);
        iWrite += iBlock;
    }

    return 0;
}

int C_CBC_MAC_MODE::Encrypt(BYTE* pIn, int iLenIn, BYTE* pOut, int* piLenOut, IBlockCipherKernel* pobjKer)
{
    int iBlock = pobjKer->GetBlockLen();
    int iRead  = 0;

    while(iRead + iBlock <= iLenIn)
    {
        C_CBC_MODE::Encrypt(pIn + iRead, iBlock, pOut, piLenOut, pobjKer);
        iRead += iBlock;
    }

    return 0;
}
